"""
CLI主模块

提供数据库备份工具的命令行主入口，负责参数解析和命令分发。
"""

import argparse
import sys
import os
import logging
import traceback
from typing import Optional, List
from .config import generate_config_file
from .cli_parse_args import ArgumentParser
from .backup.backup_executor import BackupExecutor
from .task_scheduler import TaskScheduler
from .config import create_config_manager, ConfigManager
from .cli_commands import BackupCommandExecutor
from .task_scheduler import BackupTask


class DatabaseBackupCLI:
    """数据库备份命令行接口
    
    提供完整的命令行界面，支持多种数据库备份操作。
    """
    
    def __init__(self):
        """初始化命令行接口
        
        返回:
            DatabaseBackupCLI: 命令行接口实例
        """
        self.parser = ArgumentParser()
        self.logger = self._setup_logging()
    
    def _setup_logging(self) -> logging.Logger:
        """设置日志记录
        
        返回:
            logging.Logger: 配置好的日志记录器
                示例值: <Logger database_backup.cli (INFO)>
        """
        logger = logging.getLogger('database_backup')
        logger.setLevel(logging.INFO)
        
        # 创建控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        
        # 创建格式化器
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        console_handler.setFormatter(formatter)
        
        # 添加处理器
        logger.addHandler(console_handler)
        
        return logger
    
    def parse_args(self, args: Optional[List[str]] = None) -> argparse.Namespace:
        """解析命令行参数
        
        参数:
            args (Optional[List[str]]): 命令行参数列表，None表示使用sys.argv
                示例值: ["mysql", "--host", "localhost", "--user", "root"]
        
        返回:
            argparse.Namespace: 解析后的参数对象
                示例值: Namespace(command='mysql', host='localhost', user='root')
        """
        if args is None:
            args = sys.argv[1:]
        
        return self.parser.parse_args(args)
    
    def run(self, args: Optional[List[str]] = None) -> int:
        """运行命令行接口
        
        参数:
            args (Optional[List[str]]): 命令行参数列表
                示例值: ["mysql", "--host", "localhost"]
        
        返回:
            int: 退出代码 (0表示成功，非0表示失败)
                示例值: 0
        """
        try:
            parsed_args = self.parse_args(args)
            
            # 设置详细模式
            if parsed_args.verbose:
                self.logger.setLevel(logging.DEBUG)
            
            # 设置日志文件
            if parsed_args.log_file:
                file_handler = logging.FileHandler(parsed_args.log_file)
                file_handler.setLevel(self.logger.level)
                formatter = logging.Formatter(
                    '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
                )
                file_handler.setFormatter(formatter)
                self.logger.addHandler(file_handler)
            
            # 创建配置管理器
            config_manager = create_config_manager(os.path.join(os.getcwd(), "db.toml"))
            
            # 执行相应的命令
            if not parsed_args.command:
                self.parser.print_help()
                return 1
            
            if parsed_args.command == 'backup':
                return self._run_backup_command(parsed_args, config_manager)
            elif parsed_args.command == 'generate-config':
                return self._run_config_command(parsed_args)
            else:
                self.logger.error(f"未知命令: {parsed_args.command}")
                return 1
                
        except Exception as e:
            self.logger.error(f"执行命令时发生错误: {e}")
            if parsed_args.verbose:
                self.logger.debug(traceback.format_exc())
            return 1
    
    def _run_backup_command(self, args: argparse.Namespace, config_manager) -> int:
        """执行数据库备份命令
        
        参数:
            args (argparse.Namespace): 解析后的参数
            config_manager: 配置管理器实例
        
        返回:
            int: 退出代码
                示例值: 0
        """
        try:
            # 检查是否是从配置文件执行备份
            if hasattr(args, 'from_config') and args.from_config:
                return self._run_backup_from_config_command(args)
            
            # 创建备份命令执行器
            backup_executor = BackupCommandExecutor(self.logger)
            
            # 初始化配置管理器
            config_dir = getattr(args, 'config_dir', None)
            if not config_manager.initialize_for_backup(config_dir):
                return 1
            
            # 执行备份命令
            return backup_executor.execute_backup(config_manager, config_dir)
                
        except Exception as e:
            self.logger.error(f"备份过程中发生错误: {e}")
            if args.verbose:
                self.logger.debug(traceback.format_exc())
            return 1

    def _run_config_command(self, args: argparse.Namespace) -> int:
        """执行配置生成命令
        
        参数:
            args (argparse.Namespace): 解析后的参数
        
        返回:
            int: 退出代码
                示例值: 0
        """
        try:
            # 使用新的配置生成函数
            generate_config_file(args.type, args.output)
            self.logger.info(f"配置模板已生成到: {args.output}")
            return 0
                
        except Exception as e:
            self.logger.error(f"生成配置文件时发生错误: {e}")
            if args.verbose:
                self.logger.debug(traceback.format_exc())
            return 1

    # 已删除diff和git命令方法，只保留核心功能

    def _run_backup_from_config_command(self, args) -> int:
        """执行从配置文件备份命令
        
        参数:
            args: 命令行参数
            
        返回:
            int: 退出代码
        """
        # 初始化配置管理器
        config_manager = ConfigManager(args.main_config)
        
        # 加载全局配置
        if not config_manager.initialize_global_config():
            self.logger.error("初始化全局配置失败")
            return 1
        
        # 确定配置目录
        config_dir = args.config_dir or config_manager.get_config_dir()
        self.logger.info(f"使用配置目录: {config_dir}")
        
        # 验证配置文件
        if args.validate_config:
            self.logger.info("验证配置文件...")
            if not config_manager.initialize_backup_config(config_dir):
                self.logger.error("初始化备份配置失败")
                return 1
                
            validation_result = config_manager.validate_backup_configs()
            success_count = len(validation_result['success'])
            failed_count = len(validation_result['failed'])
            
            self.logger.info(f"配置验证完成: {success_count} 个成功, {failed_count} 个失败")
            
            if failed_count > 0:
                self.logger.error("部分配置文件验证失败:")
                for config_file, error in validation_result['failed']:
                    self.logger.error(f"  {config_file}: {error}")
                return 1
            
            self.logger.info("配置验证成功，退出")
            return 0
        
        # 加载备份配置
        if not config_manager.initialize_backup_config(config_dir):
            self.logger.error("初始化备份配置失败")
            return 1
        
        # 创建备份执行器
        executor = BackupCommandExecutor(args)
        
        # 创建任务调度器
        scheduler = TaskScheduler(executor)
        
        # 获取循环间隔时间（从全局配置中读取）
        loop_interval = config_manager.get_loop_interval()
        self.logger.info(f"循环间隔时间: {loop_interval}秒")
        
        # 定义获取任务的函数
        def get_tasks():
            """获取备份任务列表
            
            每次调用都会重新加载配置文件，实现动态配置加载。
            
            返回:
                List[BackupTask]: 备份任务列表
            """
            # 重新加载配置文件
            backup_configs = config_manager.load_backup_configs()
            
            # 将配置转换为任务对象
            tasks = []
            for config in backup_configs:
                task = BackupTask(config)
                tasks.append(task)
            
            return tasks
        
        # 固定使用循环模式执行
        self.logger.info("开始循环执行备份任务")
        return scheduler.schedule_loop(get_tasks, loop_interval, None)


def main():
    """命令行入口函数
    
    返回:
        int: 退出代码
            示例值: 0
    """
    cli = DatabaseBackupCLI()
    return cli.run()


if __name__ == "__main__":
    sys.exit(main())